package com.gf.gf_data.sys.exception;

import com.gf.gf_data.dto.BaseResult;
import org.apache.shiro.authz.UnauthorizedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.dao.DataAccessException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.io.IOException;

/**
 * 异常增强类（JSON格式返回数据）
 *
 * Created by Eternal_L on 2017/12/21.
 */
@RestControllerAdvice
public class RestExceptionHandler {

    private static Logger log = LoggerFactory.getLogger(RestExceptionHandler.class);

    /**
     * 运行时异常
     */
    @ExceptionHandler(RuntimeException.class)
    public BaseResult runtimeExceptionHandler(RuntimeException ex) {
        return new BaseResult(false, 10000, ex.getMessage());
    }

    /// ------------------------------基础异常-------------------------------------------
    // 空指针异常
    @ExceptionHandler(NullPointerException.class)
    public BaseResult nullPointerExceptionHandler(NullPointerException ex) {
        return logAndFormatData(ex, 10001);
    }

    // IO异常
    @ExceptionHandler(IOException.class)
    public BaseResult ioExceptionHandler(IOException ex) {
        return logAndFormatData(ex, 10001);
    }

    // 类型转换异常
    @ExceptionHandler(ClassCastException.class)
    public BaseResult classCastExceptionHandler(ClassCastException ex) {
        return logAndFormatData(ex, 10002);
    }

    // 算术异常
    @ExceptionHandler(ArithmeticException.class)
    public BaseResult arithmeticExceptionHandler(ArithmeticException ex) {
        return logAndFormatData(ex, 10003);
    }

    // 数组越界异常
    @ExceptionHandler(IndexOutOfBoundsException.class)
    public BaseResult indexOutOfBoundsExceptionHandler(IndexOutOfBoundsException ex) {
        return logAndFormatData(ex, 10004);
    }

    // 数组存储异常
    @ExceptionHandler(ArrayStoreException.class)
    public BaseResult arrayStoreExceptionHandler(ArrayStoreException ex) {
        return logAndFormatData(ex, 10005);
    }
    // 未知方法异常
    @ExceptionHandler(NoSuchMethodException.class)
    public BaseResult noSuchMethodExceptionHandler(NoSuchMethodException ex) {
        return logAndFormatData(ex, 10006);
    }

    // 操作数据库异常（DataAccessException -> RuntimeException）
    @ExceptionHandler(DataAccessException.class)
    public BaseResult dataAccessException(DataAccessException ex) {
        return logAndFormatData(ex, 10007);
    }

    // 参数错误或非法异常
    @ExceptionHandler(IllegalArgumentException.class)
    public BaseResult numberFormatExceptionHandler(IllegalArgumentException ex) {
        return logAndFormatData(ex, 10008);
    }

    // 违背安全原则异常
    @ExceptionHandler(SecurityException.class)
    public BaseResult securityExceptionHandler(SecurityException ex) {
        return logAndFormatData(ex, 10009);
    }

    /// ----------------------------web 请求异常--------------------------------------------
    //400错误
    @ExceptionHandler({
            HttpMessageNotReadableException.class,
            TypeMismatchException.class,
            MissingServletRequestParameterException.class})
    public BaseResult request400(){
        return new BaseResult(false, 400, stateOfMsg(400));
    }

    //405错误
    @ExceptionHandler({HttpRequestMethodNotSupportedException.class})
    public BaseResult request405(){
        return new BaseResult(false, 405, stateOfMsg(405));
    }

    //406错误
    @ExceptionHandler({HttpMediaTypeNotAcceptableException.class})
    public BaseResult request406(){
        return new BaseResult(false, 406, stateOfMsg(406));
    }

    //415错误
    @ExceptionHandler({HttpMediaTypeNotSupportedException.class})
    public BaseResult request415(){
        return new BaseResult(false, 415, stateOfMsg(415));
    }


    //500错误
    @ExceptionHandler({ConversionNotSupportedException.class, HttpMessageNotWritableException.class})
    public BaseResult server500(){
        return new BaseResult(false, 500, stateOfMsg(500));
    }

    // 没有权限
    @ExceptionHandler({UnauthorizedException.class})
    public BaseResult unauthorizedException(){
        return new BaseResult(false, 403, stateOfMsg(403));
    }


    /**
     * 记录日志并格式化数据
     * @param ex
     * @param status
     * @return
     */
    private BaseResult logAndFormatData(Throwable ex, int status) {
        log(ex);
        return new BaseResult(false, status, stateOfMsg(status));
    }


    /**
     * 异常错误日志处理
     * @param ex
     */
    private static void log(Throwable ex){
        log.error(ex.getMessage(), (Object) ex.getStackTrace());
        ex.printStackTrace();
    }

    /**
     * 根据status获取异常描述信息
     *
     * @param status 状态码
     * @return       状态描述信息
     */
    private static String stateOfMsg(int status){
        return ExceptionEnum.stateOfValue(status);
    }

}
